package com.egene.tw.activity.signs.heart;

import android.graphics.Color;
import android.graphics.Typeface;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.TextView;

import com.egene.tw.R;
import com.egene.tw.activity.signs.BarChartData;
import com.egene.tw.activity.signs.BarChartItemData;
import com.egene.tw.data.DataRepository;
import com.egene.tw.data.utils.DateFormUtils;
import com.github.mikephil.charting.charts.BarChart;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.formatter.IValueFormatter;
import com.github.mikephil.charting.utils.ViewPortHandler;

import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Click;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.Extra;
import org.androidannotations.annotations.ViewById;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;

@EActivity(R.layout.activity_heart_detail)
public class HeartDetailActivity extends AppCompatActivity {
    enum DateType {
        day, week, month
    }

    @Extra
    int type;

    //ToolBar Views
    @ViewById(R.id.actionBar)
    Toolbar mToolbarView;
    @ViewById(R.id.toolbar_title)
    TextView mToolBarTitle;


    @ViewById(R.id.barChart)
    BarChart mChart;
    @ViewById(R.id.viewDay)
    TextView viewDay;
    @ViewById(R.id.viewWeek)
    TextView viewWeek;
    @ViewById(R.id.viewMonth)
    TextView viewMonth;

    @ViewById(R.id.textDateTitle)
    TextView textDateTitle;

    @ViewById(R.id.textDay1)
    TextView textDay1;
    @ViewById(R.id.textDay2)
    TextView textDay2;
    @ViewById(R.id.textDay3)
    TextView textDay3;

    @ViewById(R.id.textValuePJ)
    TextView textValuePJ;
    @ViewById(R.id.textValueHigh)
    TextView textValueHigh;
    @ViewById(R.id.textValueLow)
    TextView textValueLow;


    @ViewById(R.id.textMainTips)
    TextView textMainTips;
    @ViewById(R.id.textJKTips)
    TextView textJKTips;


    @ViewById(R.id.textChartDW)
    TextView textChartDW;


    private BarChartData barChartData;
    private long time = System.currentTimeMillis();
    private DateType dateType = DateType.day;

    @AfterViews
    void init() {
        mToolbarView.setNavigationIcon(R.drawable.ic_back);
        mToolbarView.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });

        switch (type) {
            case 0:
                day();
                break;
            case 1:
                week();
                break;
            case 2:
                month();
                break;
            default:
                day();
        }
    }

    @Click(R.id.viewDay)
    void day() {
        viewDay.setBackgroundResource(R.drawable.date_bottom_bg);
        viewWeek.setBackgroundResource(R.drawable.date_bottom_bg_1);
        viewMonth.setBackgroundResource(R.drawable.date_bottom_bg_1);

        viewDay.setTextColor(getResources().getColor(R.color.colorWhite));
        viewWeek.setTextColor(getResources().getColor(R.color.colorText));
        viewMonth.setTextColor(getResources().getColor(R.color.colorText));

        textChartDW.setText(R.string.hour_dangwei);

        time = System.currentTimeMillis();
        dateType = DateType.day;
        loadDayData();
        updateUI();
    }

    @Click(R.id.viewWeek)
    void week() {
        viewDay.setBackgroundResource(R.drawable.date_bottom_bg_1);
        viewWeek.setBackgroundResource(R.drawable.date_bottom_bg);
        viewMonth.setBackgroundResource(R.drawable.date_bottom_bg_1);

        viewDay.setTextColor(getResources().getColor(R.color.colorText));
        viewWeek.setTextColor(getResources().getColor(R.color.colorWhite));
        viewMonth.setTextColor(getResources().getColor(R.color.colorText));

        textChartDW.setText(R.string.day_dangwei);

        time = System.currentTimeMillis();
        dateType = DateType.week;
        loadWeekData();
        updateUI();
    }

    @Click(R.id.viewMonth)
    void month() {
        viewDay.setBackgroundResource(R.drawable.date_bottom_bg_1);
        viewWeek.setBackgroundResource(R.drawable.date_bottom_bg_1);
        viewMonth.setBackgroundResource(R.drawable.date_bottom_bg);

        viewDay.setTextColor(getResources().getColor(R.color.colorText));
        viewWeek.setTextColor(getResources().getColor(R.color.colorText));
        viewMonth.setTextColor(getResources().getColor(R.color.colorWhite));

        textChartDW.setText(R.string.day_dangwei);

        time = System.currentTimeMillis();
        dateType = DateType.month;
        loadMonthData();
        updateUI();
    }

    @Click(R.id.textDay1)
    void textDay1() {
        switch (dateType) {
            case day:
                if (DateFormUtils.isToday(time)) {
                    time -= DateFormUtils.DAY * 2;
                } else {
                    time -= DateFormUtils.DAY;
                }
                loadDayData();
                break;
            case week:
                if (DateFormUtils.isToWeek(time)) {
                    time -= DateFormUtils.DAY * 7 * 2;
                } else {
                    time -= DateFormUtils.DAY * 7;
                }
                loadWeekData();
                break;
            case month:
                if (DateFormUtils.isToMonth(time)) {
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTimeInMillis(time);
                    calendar.add(Calendar.MONTH, -2);
                    time = calendar.getTime().getTime();
                } else {
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTimeInMillis(time);
                    calendar.add(Calendar.MONTH, -1);
                    time = calendar.getTime().getTime();
                }
                loadMonthData();
                break;
        }
        updateUI();
    }

    @Click(R.id.textDay2)
    void textDay2() {
        switch (dateType) {
            case day:
                if (!DateFormUtils.isToday(time)) {
                    return;
                }
                time -= DateFormUtils.DAY;
                loadDayData();
                break;
            case week:
                if (!DateFormUtils.isToWeek(time)) {
                    return;
                }
                time -= DateFormUtils.DAY * 7;
                loadWeekData();
                break;
            case month:
                if (!DateFormUtils.isToMonth(time)) {
                    return;
                }
                Calendar calendar = Calendar.getInstance();
                calendar.setTimeInMillis(time);
                calendar.add(Calendar.MONTH, -1);
                time = calendar.getTime().getTime();
                loadMonthData();
                break;
        }
        updateUI();
    }

    @Click(R.id.textDay3)
    void textDay3() {
        switch (dateType) {
            case day:
                if (DateFormUtils.isToday(time)) {
                    return;
                }
                time += DateFormUtils.DAY;
                loadDayData();
                break;
            case week:
                if (DateFormUtils.isToWeek(time)) {
                    return;
                }
                time += DateFormUtils.DAY * 7;
                loadWeekData();
                break;
            case month:
                if (DateFormUtils.isToMonth(time)) {
                    return;
                }
                Calendar calendar = Calendar.getInstance();
                calendar.setTimeInMillis(time);
                calendar.add(Calendar.MONTH, 1);
                time = calendar.getTime().getTime();
                loadMonthData();
                break;
        }
        updateUI();
    }

    public void adapterCommand(BarChartData chartData) {
        barChartData = chartData;
        mChart.setNoDataText(getString(R.string.no_data));
        if (barChartData == null || barChartData.getList() == null || barChartData.getList().size() == 0) {
            return;
        }
        mChart.setScaleEnabled(false);

        Typeface mTfLight = Typeface.createFromAsset(mChart.getContext().getAssets(), "OpenSans-Light.ttf");
        mChart.getDescription().setEnabled(false);

        // scaling can now only be done on x- and y-axis separately
        mChart.setPinchZoom(false);

        mChart.setDrawBarShadow(false);
        mChart.setDrawGridBackground(false);

        Legend l = mChart.getLegend();
        l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);
        l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT);
        l.setOrientation(Legend.LegendOrientation.VERTICAL);
        l.setDrawInside(true);
        l.setTypeface(mTfLight);
        l.setYOffset(0f);
        l.setXOffset(10f);
        l.setYEntrySpace(0f);
        l.setTextSize(8f);
        l.setTextColor(Color.parseColor("#ffffff"));

        XAxis xAxis = mChart.getXAxis();
        xAxis.setTextColor(Color.parseColor("#ffffff"));
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
        xAxis.setTypeface(mTfLight);
        xAxis.setDrawGridLines(false);
        xAxis.setGranularity(1f); // only intervals of 1 day
        xAxis.setLabelCount(7);

        xAxis.setValueFormatter(new IAxisValueFormatter() {
            @Override
            public String getFormattedValue(float value, AxisBase axis) {
                if (barChartData == null
                        || barChartData.getList() == null
                        || barChartData.getList().size() < (int) value) {
                    return "";
                }
                return barChartData.getList().get((int) value).getxDesc();
            }
        });

        YAxis leftAxis = mChart.getAxisLeft();
        leftAxis.setTypeface(mTfLight);
        leftAxis.setTextColor(Color.parseColor("#ffffff"));
        leftAxis.setDrawGridLines(false);
        leftAxis.setSpaceTop(35f);
        leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true)

        mChart.getAxisRight().setEnabled(false);


        ArrayList<BarEntry> yVals1 = new ArrayList<BarEntry>();

        List<BarChartItemData> itemList = barChartData.getList();
        for (int i = 0; i < itemList.size(); i++) {
            BarChartItemData item = itemList.get(i);
            yVals1.add(new BarEntry(i, item.getTotal()));
        }


        BarDataSet set1;

        if (mChart.getData() != null && mChart.getData().getDataSetCount() > 0) {
            set1 = (BarDataSet) mChart.getData().getDataSetByIndex(0);
            set1.setValues(yVals1);
            mChart.getData().notifyDataChanged();
            mChart.notifyDataSetChanged();
            mChart.invalidate();
        } else {
            // create 4 DataSets
            set1 = new BarDataSet(yVals1, getString(R.string.heart));
            set1.setColors(Color.parseColor("#eb5757"));
            set1.setValueTextColor(Color.parseColor("#ffffff"));

            BarData data = new BarData(set1);
            data.setValueFormatter(new IValueFormatter() {
                @Override
                public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
                    if(value == 0){
                        return "";
                    }
                    return "" + (int) value;
                }
            });
            data.setValueTypeface(mTfLight);

            mChart.setData(data);
            mChart.invalidate();
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    //
    ///////////////////////////////////////////////////////////////////////////

    private void loadDayData() {
        loadDayAnalysis();
        DataRepository.getInstance()
                .heartBarDataByDay(time)
                .subscribe(new Observer<BarChartData>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(BarChartData barChartData) {
                        adapterCommand(barChartData);
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    private void loadWeekData() {
        loadWeelAnalysis();
        DataRepository.getInstance()
                .heartBarDataByWeek(time)
                .subscribe(new Observer<BarChartData>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(BarChartData barChartData) {
                        adapterCommand(barChartData);
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    private void loadMonthData() {
        loadMonthAnalysis();
        DataRepository.getInstance()
                .heartBarDataByMonth(time)
                .subscribe(new Observer<BarChartData>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(BarChartData barChartData) {
                        adapterCommand(barChartData);
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    ///////////////////////////////////////////////////////////////////////////
    //
    ///////////////////////////////////////////////////////////////////////////
    private void loadDayAnalysis() {
        DataRepository.getInstance()
                .heartAnalysisByDay(time)
                .subscribe(new Observer<int[]>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(int[] ints) {
                        textValuePJ.setText("" + ints[0]);
                        textValueHigh.setText("" + ints[1]);
                        textValueLow.setText("" + ints[2]);

                        updateJKTips(ints[0]);
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    private void loadWeelAnalysis() {
        DataRepository.getInstance()
                .heartAnalysisByWeek(time)
                .subscribe(new Observer<int[]>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(int[] ints) {
                        textValuePJ.setText("" + ints[0]);
                        textValueHigh.setText("" + ints[1]);
                        textValueLow.setText("" + ints[2]);

                        updateJKTips(ints[0]);
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    private void loadMonthAnalysis() {
        DataRepository.getInstance()
                .heartAnalysisByMonth(time)
                .subscribe(new Observer<int[]>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(int[] ints) {
                        textValuePJ.setText("" + ints[0]);
                        textValueHigh.setText("" + ints[1]);
                        textValueLow.setText("" + ints[2]);

                        updateJKTips(ints[0]);
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }


    private void updateUI() {
        updateTitle();
        updateBg(2);
        SimpleDateFormat sdf;
        switch (dateType) {
            case day:
                sdf = new SimpleDateFormat("MM/dd");
                if (DateFormUtils.isToday(time)) {
                    textDay1.setText(sdf.format(time - DateFormUtils.DAY * 2));
                    textDay2.setText(sdf.format(time - DateFormUtils.DAY));
                    textDay3.setText(R.string.today);
                    updateBg(3);
                } else {
                    textDay1.setText(sdf.format(time - DateFormUtils.DAY));
                    textDay2.setText(sdf.format(time));
                    if (DateFormUtils.isToday(time + DateFormUtils.DAY)) {
                        textDay3.setText(R.string.today);
                    } else {
                        textDay3.setText(sdf.format(time + DateFormUtils.DAY));
                    }
                }
                break;
            case week:
                if (DateFormUtils.isToWeek(time)) {
                    textDay1.setText(DateFormUtils.weekBetwwDesc(time - DateFormUtils.DAY * 7 * 2));
                    textDay2.setText(DateFormUtils.weekBetwwDesc(time - DateFormUtils.DAY * 7));
                    textDay3.setText(R.string.toweek);
                    updateBg(3);
                } else {
                    textDay1.setText(DateFormUtils.weekBetwwDesc(time - DateFormUtils.DAY * 7));
                    textDay2.setText(DateFormUtils.weekBetwwDesc(time));
                    if (DateFormUtils.isToWeek(time + DateFormUtils.DAY * 7)) {
                        textDay3.setText(R.string.toweek);
                    } else {
                        textDay3.setText(DateFormUtils.weekBetwwDesc(time + DateFormUtils.DAY * 7));
                    }
                }
                break;
            case month:
                sdf = new SimpleDateFormat("MM月");
                if (DateFormUtils.isToMonth(time)) {
                    sdf = new SimpleDateFormat("MM月");
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTimeInMillis(time);
                    calendar.add(Calendar.MONTH, -2);
                    textDay1.setText(sdf.format(calendar.getTime()));
                    calendar.add(Calendar.MONTH, 1);
                    textDay2.setText(sdf.format(calendar.getTime()));
                    textDay3.setText(R.string.tomonth);
                    updateBg(3);
                } else {
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTimeInMillis(time);
                    calendar.add(Calendar.MONTH, -1);
                    textDay1.setText(sdf.format(calendar.getTime()));
                    calendar.add(Calendar.MONTH, 1);
                    textDay2.setText(sdf.format(calendar.getTime()));
                    calendar.add(Calendar.MONTH, 1);
                    if (DateFormUtils.isToMonth(calendar.getTime().getTime())) {
                        textDay3.setText(R.string.tomonth);
                    } else {
                        textDay3.setText(sdf.format(calendar.getTime()));
                    }
                }
                break;
        }
    }

    private void updateBg(int index) {
        SimpleDateFormat sdf;
        switch (index) {
            case 1:
                textDay1.setBackgroundResource(R.drawable.date_btn_bg_1);
                textDay2.setBackgroundResource(R.drawable.date_btn_bg);
                textDay3.setBackgroundResource(R.drawable.date_btn_bg);

                textDay1.setTextColor(getResources().getColor(R.color.colorText));
                textDay2.setTextColor(getResources().getColor(R.color.colorWhite));
                textDay3.setTextColor(getResources().getColor(R.color.colorWhite));
                break;
            case 2:
                textDay1.setBackgroundResource(R.drawable.date_btn_bg);
                textDay2.setBackgroundResource(R.drawable.date_btn_bg_1);
                textDay3.setBackgroundResource(R.drawable.date_btn_bg);

                textDay1.setTextColor(getResources().getColor(R.color.colorWhite));
                textDay2.setTextColor(getResources().getColor(R.color.colorText));
                textDay3.setTextColor(getResources().getColor(R.color.colorWhite));

                break;
            case 3:
                textDay1.setBackgroundResource(R.drawable.date_btn_bg);
                textDay2.setBackgroundResource(R.drawable.date_btn_bg);
                textDay3.setBackgroundResource(R.drawable.date_btn_bg_1);

                textDay1.setTextColor(getResources().getColor(R.color.colorWhite));
                textDay2.setTextColor(getResources().getColor(R.color.colorWhite));
                textDay3.setTextColor(getResources().getColor(R.color.colorText));

                break;
        }
    }

    private void updateTitle() {
        SimpleDateFormat sdf;
        switch (dateType) {
            case day:
                sdf = new SimpleDateFormat("yyyy/MM/dd");
                textDateTitle.setText(sdf.format(time));
                break;
            case week:
                textDateTitle.setText(DateFormUtils.weekBetwwDescTitle(time));
                break;
            case month:
                sdf = new SimpleDateFormat("MM月");
                textDateTitle.setText(sdf.format(time));
                break;
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    //
    ///////////////////////////////////////////////////////////////////////////

    private void updateJKTips(int pj) {
        if (pj == 0) {
            textMainTips.setText(R.string.nodate_anilys);
            textJKTips.setText("");
        } else {
            textMainTips.setText(R.string.heart_main_tips);
            textJKTips.setText(getJKTips(pj));
        }
    }

    private String getJKTips(int pj) {
        String tips = "";
        if (pj <= 104) {
            switch (dateType) {
                case day:
                    tips = getString(R.string.heart_day_1);
                    break;
                case week:
                    tips = getString(R.string.heart_week_1);
                    break;
                case month:
                    tips = getString(R.string.heart_month_1);
                    break;
            }
        } else if (pj <= 109) {
            switch (dateType) {
                case day:
                    tips = getString(R.string.heart_day_2);
                    break;
                case week:
                    tips = getString(R.string.heart_week_2);
                    break;
                case month:
                    tips = getString(R.string.heart_month_2);
                    break;
            }
        } else if (pj <= 119) {
            switch (dateType) {
                case day:
                    tips = getString(R.string.heart_day_3);
                    break;
                case week:
                    tips = getString(R.string.heart_week_3);
                    break;
                case month:
                    tips = getString(R.string.heart_month_3);
                    break;
            }
        } else {
            switch (dateType) {
                case day:
                    tips = getString(R.string.heart_day_4);
                    break;
                case week:
                    tips = getString(R.string.heart_week_4);
                    break;
                case month:
                    tips = getString(R.string.heart_month_4);
                    break;
            }
        }
        return tips;
    }
}
